#include <iostream>
#include <string>

#include "../add_contact.pb.h"
#include "../httplib.h"
#include "../contactException.h"

const std::string DEFAULT_HOST = "127.0.0.1";
const uint16_t DEFAULT_PORT = 8080;

void meau() {
    std::cout
        << "-----------------------------------------------------" << std::endl
        << "--------------- 请选择对通讯录的操作 ----------------" << std::endl
        << "------------------ 1、新增联系人 --------------------" << std::endl
        << "------------------ 2、删除联系人 --------------------" << std::endl
        << "------------------ 3、查看联系人列表 ----------------" << std::endl
        << "------------------ 4、查看联系人详细信息 ------------" << std::endl
        << "------------------ 0、退出 --------------------------" << std::endl
        << "-----------------------------------------------------" << std::endl;
}

enum Option { EXIT = 0, APPEND, DEL, VIEW, SEARCH };

void buildAddContactRequest(add_contact::AddContactRequest* req) {
    std::cout << "-------------新增联系人-------------" << std::endl;

    std::cout << "please input name: ";
    std::string name;
    std::getline(std::cin, name);
    req->set_name(name);

    std::cout << "please input age: ";
    int age = 0;
    std::cin >> age;
    std::cin.ignore(256, '\n');
    req->set_age(age);

    std::cout << "please input phone number(input Enter only to stop)"
              << std::endl;
    std::string phone;
    while (true) {
        std::cout << "phone number: ";
        std::getline(std::cin, phone);
        if (phone.empty()) {
            break;
        }

        add_contact::Phone* c_phone = req->add_phones();
        c_phone->set_number(phone);

        std::cout << "please input phone number type(1 - MP, 2 - TEL): ";
        int type = 0;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type) {
            case 1:
                c_phone->set_phone_type(
                    add_contact::Phone::PhoneType::Phone_PhoneType_MP);
                break;
            case 2:
                c_phone->set_phone_type(
                    add_contact::Phone::PhoneType::Phone_PhoneType_TEL);
                break;
            default:
                break;
        }
    }

    std::cout << "-----------添加联系人成功-----------" << std::endl;
}

void addContact() {
    std::string err_desc;
    add_contact::Response resp;

    do {
        // 1. 构造 add 请求
        add_contact::AddContactRequest req;
        buildAddContactRequest(&req);

        // 2. 序列化 add 请求
        std::string req_str;
        if (!req.SerializeToString(&req_str)) {
            err_desc += "请求序列化失败";
            break;
        }

        // 3. 发起 post 调用
        httplib::Client client(DEFAULT_HOST, DEFAULT_PORT);
        auto res =
            client.Post("/contacts/add", req_str, " application/protobuf");
        if (!res) {
            err_desc += "/contacts/add 链接失败";
            break;
        }

        // 4. 反序列化响应
        bool is_success = resp.ParseFromString(res->body);
        if (res->status != 200 && !is_success) {
            err_desc += "/contacts/add 调用失败";
            err_desc += res->reason;
        } else if (res->status != 200) {
            err_desc += "/contacts/add 调用失败";
            err_desc += res->reason;
            err_desc += "错误原因: ";
            err_desc += resp.err_desc();
        } else if (!resp.is_success()) {
            err_desc += "/contacts/add 结果错误";
            err_desc += "错误原因: ";
            err_desc += resp.err_desc();
        }
    } while (0);

    // 5. 结果打印
    if (err_desc.empty()) {
        std::cout << "新增联系人成功, uid: " << resp.uid() << std::endl;

    } else {
        throw(ContactException(err_desc));
    }
}

int main() {
    while (true) {
        meau();

        int opt = -1;
        std::cin >> opt;
        std::cin.ignore(256, '\n');

        try {
            switch (opt) {
                case Option::EXIT:
                    std::cout << "程序退出...." << std::endl;
                    return 0;
                case Option::APPEND:
                    addContact();
                    break;
                case Option::DEL:
                    break;
                case Option::SEARCH:
                    break;
                case Option::VIEW:
                    break;
                default:
                    std::cout << "无效的输入, 请重新选择" << std::endl;
                    break;
            }
        } catch (const ContactException& e) {
            std::cout << "请求处理异常: " << e.what() << std::endl;
        }
    }

    return 0;
}